package com.sinosun.autotestmachine.tools.parser;

import java.lang.reflect.InvocationTargetException;

import org.json.JSONException;
import org.json.JSONObject;

import com.sinosun.autotestmachine.App;
import com.sinosun.autotestmachine.Element;
import com.sinosun.autotestmachine.tools.TaskManager;
import com.sinosun.autotestmachine.tools.Excutor.StepExcutor;
import com.sinosun.autotestmachine.tools.proxy.ErrorCode;

import android.text.TextUtils;
import android.util.Log;

/**
 * 步骤解析器
 * @author HYW
 *
 */
public class StepParser {
	
	private final String STEP_DECRIPTION = "stepDecription";
	private final String EXPECTEDRESULT = "expectedResult";
	private final String EXCUTE_RESULT = "excuteResult";
	private final String METHOD_NAME = "methodName";
	private final String PARAM = "param";
	private final String CACHE_PARAM = "cacheParam";
	private final String ASYNC = "async";
	private StepInformation clearStepInfo = new StepInformation("sycnLogout");
	private static StepParser instance = null;
	
	private StepParser() { }
	
	public synchronized static StepParser getStepParser() {
		if (instance == null) {
			instance = new StepParser();
		}
		return instance;
	}

	public int parser(final long caseId, final Class clazz, final Object obj, String content, final String taskId){
		try {
			final StepInformation stepInformation = new StepInformation();
			JSONObject stepJsonObject = new JSONObject(content);
			if (stepJsonObject.has(STEP_DECRIPTION)) {
				stepInformation.setStepDecription(stepJsonObject.getString(STEP_DECRIPTION));
			}
			
			int expectResult = 0;
			if (stepJsonObject.has(EXPECTEDRESULT)) {
				expectResult = stepJsonObject.getInt(EXPECTEDRESULT);
				stepInformation.setExpectedResult(expectResult);
			} else {
				return ErrorCode.ERR_PARAM_ERROR;
			}
			
			String methodName = new String();
			if (stepJsonObject.has(METHOD_NAME)) {
				methodName = stepJsonObject.getString(METHOD_NAME);
				stepInformation.setMethodName(methodName);
			} else {
				return ErrorCode.ERR_PARAM_ERROR;
			}
			
			if (stepJsonObject.has(PARAM)) {
				stepInformation.setParam(stepJsonObject.getString(PARAM));
			}
			
			if (stepJsonObject.has(CACHE_PARAM)) {
				String tmp = stepJsonObject.getString(CACHE_PARAM);
				if (TextUtils.isEmpty(tmp) || (tmp.startsWith("{") && tmp.endsWith("}") && tmp.length() == 2)) {
					tmp = new String("");
				}
				stepInformation.setCacheParam(tmp);
			}
			
			if (stepJsonObject.has(ASYNC)) {
				int async = stepJsonObject.getInt(ASYNC);
				if (async == 0) {
					stepInformation.setSyncFlag(true);
				} else {
					stepInformation.setSyncFlag(false);
				}
			}
			
			if (stepInformation.getSyncFlag()) {
				Log.e("XXX", "sync step");
				TaskManager.getTaskManager().startWaitToEnd();
				int breakFlag = 0;
				for (int i = App.allInfo.size() - 1; i >= 0; i--) {
					if (App.allInfo.get(i).getIndex() == (int) caseId && App.allInfo.get(i).getEleFlag() != 0 && App.allInfo.get(i).getTaskId().equals(taskId)) {
						breakFlag = App.allInfo.get(i).getEleFlag();
						break;
					}
				}
				if (breakFlag != 0) {		//存在异步与预期不相符的，执行清理操作
					StepExcutor.excuteStep(clazz, obj, clearStepInfo);
					return breakFlag;		//返回最后的失败情况
				} else {
					int realRet = runStep(caseId, clazz, obj, stepInformation, taskId);
					if (realRet != ErrorCode.SUCCESS) {		//同步失败时清理环境
						StepExcutor.excuteStep(clazz, obj, clearStepInfo);
					}
					return realRet;
				}
			} else {
				Log.e("XXX", "async step");
				Thread t = new Thread() {
					@Override public void run() {
						try {
							runStep(caseId, clazz, obj, stepInformation, taskId);
						} catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException
								| NoSuchMethodException | JSONException e) {
							e.printStackTrace();
						}
					}
				};
				TaskManager.getTaskManager().addThread(t);		//异步的任务等待同步任务的回收动作进行返回
			}
			
		} catch (JSONException e) {
			e.printStackTrace();
			return ErrorCode.ERR_UNEXPECT_RESULT;
		} catch (IllegalAccessException e) {
			e.printStackTrace();
			return ErrorCode.ERR_UNEXPECT_RESULT;
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
			return ErrorCode.ERR_UNEXPECT_RESULT;
		} catch (InvocationTargetException e) {
			e.printStackTrace();
			return ErrorCode.ERR_UNEXPECT_RESULT;
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
			return ErrorCode.ERR_UNEXPECT_RESULT;
		}
		return ErrorCode.SUCCESS;
	}
	
	private int runStep(final long caseId, final Class clazz, final Object obj, StepInformation stepInformation, String taskId) 
			throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, JSONException {
		Log.e("XXX", "===> start step " + stepInformation.getStepDecription() + " with expect result " + stepInformation.getExpectedResult());
		int flag = StepExcutor.excuteStep(clazz, obj, stepInformation);
		Log.e("XXX", "===> end step with flag " + flag + " <> " + stepInformation.getStepDecription());
		JSONObject jo = new JSONObject();
		jo.put(EXPECTEDRESULT, stepInformation.getExpectedResult());
		jo.put(METHOD_NAME, stepInformation.getMethodName());
		jo.put(EXCUTE_RESULT, flag);
		
		Element e = new Element((int)caseId);
		int sendFlag = 0;
		if (flag == stepInformation.getExpectedResult()) {
			sendFlag = 0;
		} else {
			sendFlag = ErrorCode.ERR_UNEXPECT_RESULT;
		}
		e.setEleFlag(sendFlag);
		e.setEleStr(jo.toString() + ",");
		e.setTaskId(taskId);
		TaskManager.getTaskManager().sendPrintCmd(e);
		return e.getEleFlag();		//返回与预期的比较结果
	}
}
